package com.ruoyi.ade.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;

import java.util.List;

/**
 * AdeLabKfoldResult对象 ade_lab_kfold_result
 * 
 * @author wxh
 * @date 2025-06-29
 */
public class AdeLabKfoldResult extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** ID */
    private Integer id;

    /** Lab ID */
    @Excel(name = "Lab ID")
    private Long labId;

    /** Algorithm */
    @Excel(name = "Algorithm")
    private String algorithm;

    @Excel(name = "PromptType")
    private String promptType;

    @Excel(name = "LLM")
    private String llm;

    /** Ade Match Level */
    @Excel(name = "Ade Match Level")
    private String adeMatchLevel;

    /** Folds */
    @Excel(name = "Folds")
    private Long folds;

    /** Precision Mean */
    @Excel(name = "Precision Mean")
    private Float precisionMean;

    /** Precision sd */
    @Excel(name = "Precision sd")
    private Float precisionSd;

    /** Recall Mean */
    @Excel(name = "Recall Mean")
    private Float recallMean;

    /** Recall sd */
    @Excel(name = "Recall sd")
    private Float recallSd;

    /** F1 Mean */
    @Excel(name = "F1 Mean")
    private Float f1Mean;

    /** F1 sd */
    @Excel(name = "F1 sd")
    private Float f1Sd;

    /** FPR Mean */
    @Excel(name = "FPR Mean")
    private Float fprMean;

    /** FPR sd */
    @Excel(name = "FPR sd")
    private Float fprSd;

    /** FNR Mean */
    @Excel(name = "FNR Mean")
    private Float fnrMean;

    /** FNR sd */
    @Excel(name = "FNR sd")
    private Float fnrSd;

    /** Specificity Mean */
    @Excel(name = "Specificity Mean")
    private Float specificityMean;

    /** Specificity sd */
    @Excel(name = "Specificity sd")
    private Float specificitySd;

    private Float accuracyMean;
    private Float accuracySd;

    public AdeLabKfoldResult(){

    }

    public AdeLabKfoldResult(Long labId, String algorithm,String promptType,String llm, String adeMatchLevel, List<AdeLabResult> results)
    {
        this.labId = labId;
        this.promptType = promptType;
        this.llm = llm;
        this.adeMatchLevel = adeMatchLevel;
        this.algorithm = algorithm;
        int size = results.size();
        this.folds = new Long(size);
        float[] precision = new float[size];
        float[] recall = new float[size];
        float[] f1 = new float[size];
        float[] accuracy = new float[size];
        float[] specificity = new float[size];
        float[] fpr = new float[size];
        float[] fnr = new float[size];
        int index = 0;
        for(AdeLabResult result:results){
            precision[index] = result.getPrecision();
            recall[index] = result.getRecall();
            f1[index] = result.getF1();
            accuracy[index] = result.getAccuracy();
            specificity[index] = result.getSpecificity();
            fpr[index] = result.getFpr();
            fnr[index] = result.getFnr();
            index++;
        }
        this.precisionMean = calculateMean(precision);
        this.recallMean = calculateMean(recall);
        this.f1Mean = calculateMean(f1);
        this.accuracyMean = calculateMean(accuracy);
        this.specificityMean = calculateMean(specificity);
        this.fprMean = calculateMean(fpr);
        this.fnrMean = calculateMean(fnr);

        this.precisionSd = calculateStdDev( precision,this.precisionMean);
        this.recallSd = calculateStdDev( recall,this.recallMean);
        this.f1Sd = calculateStdDev( f1,this.f1Mean);
        this.accuracySd = calculateStdDev( accuracy,this.accuracyMean);
        this.specificitySd = calculateStdDev( specificity,this.specificityMean);
        this.fprSd = calculateStdDev( fpr,this.fprMean);
        this.fnrSd = calculateStdDev( fnr,this.fnrMean);
    }

    private float calculateMean(float[] data){
        float sum = 0.0f;
        for(float value : data){
            sum += value;
        }
        return sum / data.length;
    }
    private float calculateStdDev(float[] data, float mean){
        float sum = 0.0f;
        for(float value : data){
            sum += Math.pow(value - mean, 2);
        }
        float result = sum/(data.length-1);
        return (float) Math.sqrt(result);
    }



    public void setId(Integer id) 
    {
        this.id = id;
    }

    public Integer getId() 
    {
        return id;
    }

    public void setAlgorithm(String algorithm) 
    {
        this.algorithm = algorithm;
    }

    public String getAlgorithm() 
    {
        return algorithm;
    }

    public void setLabId(Long labId) 
    {
        this.labId = labId;
    }

    public Long getLabId() 
    {
        return labId;
    }

    public void setAdeMatchLevel(String adeMatchLevel) 
    {
        this.adeMatchLevel = adeMatchLevel;
    }

    public String getAdeMatchLevel() 
    {
        return adeMatchLevel;
    }

    public void setFolds(Long folds) 
    {
        this.folds = folds;
    }

    public Long getFolds() 
    {
        return folds;
    }

    public Float getPrecisionMean() {
        return precisionMean;
    }

    public void setPrecisionMean(Float precisionMean) {
        this.precisionMean = precisionMean;
    }

    public Float getPrecisionSd() {
        return precisionSd;
    }

    public void setPrecisionSd(Float precisionSd) {
        this.precisionSd = precisionSd;
    }

    public Float getRecallMean() {
        return recallMean;
    }

    public void setRecallMean(Float recallMean) {
        this.recallMean = recallMean;
    }

    public Float getRecallSd() {
        return recallSd;
    }

    public void setRecallSd(Float recallSd) {
        this.recallSd = recallSd;
    }

    public Float getF1Mean() {
        return f1Mean;
    }

    public void setF1Mean(Float f1Mean) {
        this.f1Mean = f1Mean;
    }

    public Float getF1Sd() {
        return f1Sd;
    }

    public void setF1Sd(Float f1Sd) {
        this.f1Sd = f1Sd;
    }

    public Float getFprMean() {
        return fprMean;
    }

    public void setFprMean(Float fprMean) {
        this.fprMean = fprMean;
    }

    public Float getFprSd() {
        return fprSd;
    }

    public void setFprSd(Float fprSd) {
        this.fprSd = fprSd;
    }

    public Float getFnrMean() {
        return fnrMean;
    }

    public void setFnrMean(Float fnrMean) {
        this.fnrMean = fnrMean;
    }

    public Float getFnrSd() {
        return fnrSd;
    }

    public void setFnrSd(Float fnrSd) {
        this.fnrSd = fnrSd;
    }

    public Float getSpecificityMean() {
        return specificityMean;
    }

    public void setSpecificityMean(Float specificityMean) {
        this.specificityMean = specificityMean;
    }

    public Float getSpecificitySd() {
        return specificitySd;
    }

    public void setSpecificitySd(Float specificitySd) {
        this.specificitySd = specificitySd;
    }

    public Float getAccuracyMean() {
        return accuracyMean;
    }

    public void setAccuracyMean(Float accuracyMean) {
        this.accuracyMean = accuracyMean;
    }

    public Float getAccuracySd() {
        return accuracySd;
    }

    public void setAccuracySd(Float accuracySd) {
        this.accuracySd = accuracySd;
    }

    public String getPromptType() {
        return promptType;
    }

    public void setPromptType(String promptType) {
        this.promptType = promptType;
    }

    public String getLlm() {
        return llm;
    }

    public void setLlm(String llm) {
        this.llm = llm;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("id", getId())
            .append("algorithm", getAlgorithm())
            .append("labId", getLabId())
            .append("adeMatchLevel", getAdeMatchLevel())
            .append("folds", getFolds())
            .append("precisionMean", getPrecisionMean())
            .append("precisionSd", getPrecisionSd())
            .append("recallMean", getRecallMean())
            .append("recallSd", getRecallSd())
            .append("f1Mean", getF1Mean())
            .append("f1Sd", getF1Sd())
            .append("fprMean", getFprMean())
            .append("fprSd", getFprSd())
            .append("fnrMean", getFnrMean())
            .append("fnrSd", getFnrSd())
            .append("specificityMean", getSpecificityMean())
            .append("specificitySd", getSpecificitySd())
            .append("createTime", getCreateTime())
            .toString();
    }
}
